﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JMT.Data
{
    public class JData
    {
        private static JData s_instance = new JData();
        public static JData Current
        {
            get
            {
                return s_instance;
            }
        }

        private JEventBus _eventBus;

        public JSolution Solution { get; set; }

        public ModelNameCreator NameCreator { get; set; }

        private JData()
        {
            _eventBus = JEventBus.GetInstance();
            NameCreator = new ModelNameCreator();
        }

        public T AddModel<T>(IJContainer jContainer) where T : JModel
        {
            string type = JMetadata.GetModelName(typeof(T));
            JModel jModel = JModelFactory.Create<T>();
            jContainer.Add(jModel);
            _eventBus.Publish(new Events.AddModelEvent(jContainer, jModel));
            return (T)jModel;
        }

        public JModel AddModel(IJContainer jContainer, JModel jModel)
        {
            jContainer.Add(jModel);
            _eventBus.Publish(new Events.AddModelEvent(jContainer, jModel));
            return jModel;
        }


        //public void AddModel(IJContainer jContainer, JModel jModel)
        //{
        //    jContainer.Add(jModel);

        //    //_eventBus.Publish(new Events.AddModelEvent<T>(jContainer, jModel));
        //}

        //public void RemoveModel(IJContainer jContainer, JModel jModel)
        //{
        //    jContainer.Remove(jModel);
        //}

        public List<JRelation> GetRelations(JModel jModel)
        {
            List<JRelation> relations = Solution.GetChildren<JRelation>();
            return relations.Where(p => p.FromId == jModel.Id || p.ToId == jModel.Id).ToList();
        }
    }

    public class JEventBus
    {
        public Dictionary<string, List<IEventHandler>> _eventDict;
        private static JEventBus s_instance;
        public static JEventBus GetInstance()
        {
            if (s_instance == null)
            {
                s_instance = new JEventBus();
            }
            return s_instance;
        }

        private JEventBus()
        {
            _eventDict = new Dictionary<string, List<IEventHandler>>();
        }

        public void OnEvent()
        {
        }

        public void Register(string eventId, IEventHandler handler)
        {
            if (!_eventDict.ContainsKey(eventId))
            {
                _eventDict.Add(eventId, new List<IEventHandler>());
            }
            _eventDict[eventId].Add(handler);
        }

        /// <summary>
        /// 发布事件
        /// </summary>
        /// <param name="event"></param>
        public void Publish(EventBase @event)
        {
            string identity = @event.GetIdentity();

            System.Diagnostics.Debug.WriteLine("fire event:" + @event.GetIdentity());
            if (_eventDict.ContainsKey(identity))
            {
                List<IEventHandler> handlers = _eventDict[identity];
                foreach (var handler in handlers)
                {
                    handler.Handle(@event);
                }
            }
        }
    }

    public abstract class EventBase
    {
        public string Product { get; set; }
        public string Module { get; set; }
        public string Name { get; set; }
        public EventBase(string product, string module, string name)
        {
            Product = product;
            Module = module;
            Name = name;
        }

        public string GetIdentity()
        {
            return string.Format("{0}.{1}.{2}", Product, Module, Name);
        }
    }

    public interface IEventHandler
    {
        void Handle(EventBase @event);
    }
}
